package away3d.animators.data ;


import away3d.core.base.Geometry ;
import away3d.core.base.IRenderable ;
import away3d.core.base.SubGeometry ;
import away3d.core.base.SubMesh ;
import away3d.materials.passes.MaterialPassBase ;
import flash.display3D.Context3D ;
import flash.display3D.Context3DProgramType ;
import flash.display3D.Context3DVertexBufferFormat ;



/**
 * VertexAnimationState defines the state for a given Mesh and VertexAnimation. The state consists out of the current
 * poses as Geometry, and their respective blend weights.
 *
 * @see away3d.core.animation.vertex.VertexAnimation
 */
class VertexAnimationState extends AnimationStateBase
{
    
    
    public var _poses               : Vector<Geometry> ;
    
    // keep a narrowly typed reference
    private var _vertexAnimation    : VertexAnimation ;
    private var _weights            : Vector<Float> ;
    
    
    
    /**
     * Creates a VertexAnimationState object.
     * @param animation The animation object the state refers to.
     */
    public function new( animation : VertexAnimation )
    {
        
        super( animation );
        
        _vertexAnimation    = animation ;
        _weights            = Vector( [ 1, 0, 0, 0 ] ) ;
        _poses              = new Vector() ;
        
    }
    
    
    public function weights( get_weights, null ) : Vector<Float> ;
    
    
    /**
     * The blend weights per pose, must be values between 0 and 1.
     */
    public function get_weights() : Vector<Float>
    {
        
        return _weights ;
        
    }
    
    
    /**
     * The blend poses that will be used to compute the final pose.
     */
    public function get_poses() : Vector<Geometry>
    {
        
        return _poses ;
        
    }
    
    
    /**
     * @inheritDoc
     */
     override public function setRenderState(   context         : Context3D
                                            ,   contextIndex    : Int
                                            ,   pass            : MaterialPassBase
                                            ,   renderable      : IRenderable
                                            )
    {
        
        var i :     Int;
        var len         = _vertexAnimation._numPoses ;
        var index       = _vertexAnimation._streamIndex ;
        var j :     Int = 0 ; //this was defined lower but seems wrong
        
        // if no poses defined, set temp data
        if( !_poses.length )
        {
            
            if( _vertexAnimation.blendMode == VertexAnimationMode.ABSOLUTE )
            {
                for( i in 1...len )
                {
                    //TODO: j looks like an error here moved it's definition up and assumed it to start at 0?
                    context.setVertexBufferAt   (   index + ( j++ )
                                                ,   renderable.getVertexBuffer( context, contextIndex )
                                                ,   0
                                                ,   Context3DVertexBufferFormat.FLOAT_3
                                                ) ;
                                                
                    context.setProgramConstantsFromVector( Context3DProgramType.VERTEX
                                                         , pass.numUsedVertexConstants
                                                         , _weights
                                                         , 1
                                                         );
                    
                    if (_vertexAnimation._useNormals) 
                    {
                        
                        context.setVertexBufferAt   ( index + ( j++ )
                                                    , renderable.getVertexNormalBuffer( context, contextIndex )
                                                    , 0
                                                    , Context3DVertexBufferFormat.FLOAT_3
                                                    );
                    }
                    
                }
                    
            }
            // todo: set temp data for additive?
            return;
                
        }
        
        // this type of animation can only be SubMesh
        var subMesh = SubMesh( renderable ) ;
        var subGeom : SubGeometry ;
        
        
        if( _vertexAnimation.blendMode == VertexAnimationMode.ABSOLUTE )
        {
            
            i = 1;
            subGeom = _poses[ uint( 0 ) ].subGeometries[ subMesh._index ] ;
            if (subGeom) subMesh.subGeometry = subGeom;
            
        }
        else 
        {
            
            i = 0;
            
        }
        
        // set the base sub-geometry so the material can simply pick up on this data
        
        
        
        for ( i in 0...len )
        {
            
            subGeom = _poses[ i ].subGeometries[ subMesh._index ] || subMesh.subGeometry ;
            context.setVertexBufferAt   (   index + ( j++ )
                                        ,   subGeom.getVertexBuffer( context, contextIndex )
                                        ,   0
                                        ,   Context3DVertexBufferFormat.FLOAT_3
                                        ) ;
            
            context.setProgramConstantsFromVector   (   Context3DProgramType.VERTEX
                                                    ,   pass.numUsedVertexConstants
                                                    ,   _weights
                                                    ,   1
                                                    ) ;
            
            if( _vertexAnimation._useNormals )
            {
                
                context.setVertexBufferAt   (   index + ( j++ )
                                            ,   subGeom.getVertexNormalBuffer( context, contextIndex )
                                            ,   0
                                            ,   Context3DVertexBufferFormat.FLOAT_3
                                            ) ;
                
            }
            
        }
        
    }
    
    
    /**
     * @inheritDoc
     */
    override public function clone() : AnimationStateBase
    {
        
        var clone       = new VertexAnimationState( _vertexAnimation ) ;
        clone._poses    = _poses ;
        clone._weights  = _weights ;
        
        return clone ;
        
    }
    
    
}